package com.invengo.module_check.ui.fragment.get_in_car;

import android.annotation.SuppressLint;
import android.app.Application;
import android.os.Build;
import android.text.TextUtils;

import com.invengo.base.utils.BeanMapperUtils;
import com.invengo.library_db.entity.module_check.BookBean;
import com.invengo.library_rfid.classify.AnalyzeImpl;
import com.invengo.library_rfid.classify.RFIDCallBackListener;
import com.invengo.library_rfid.entity.TagInfo;
import com.invengo.module_check.BR;
import com.invengo.module_check.R;
import com.invengo.module_check.data.repsitory.business.BusinessRepsitory;
import com.invengo.module_check.ui.fragment.get_in_car.item.GetInCarItemViewModel;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import androidx.annotation.NonNull;
import androidx.databinding.ObservableArrayList;
import androidx.databinding.ObservableField;
import androidx.databinding.ObservableList;
import io.reactivex.Observable;
import java8.util.J8Arrays;
import java8.util.stream.StreamSupport;
import me.goldze.mvvmhabit.base.BaseViewModel;
import me.goldze.mvvmhabit.binding.command.BindingCommand;
import me.goldze.mvvmhabit.bus.Messenger;
import me.goldze.mvvmhabit.bus.event.SingleLiveEvent;
import me.goldze.mvvmhabit.http.BaseBean;
import me.goldze.mvvmhabit.utils.RxUtils;
import me.goldze.mvvmhabit.utils.ToastUtils;
import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter;
import me.tatarka.bindingcollectionadapter2.ItemBinding;

import static me.goldze.mvvmhabit.utils.constant.Constants.TOKEN_CAMERA;

public class GetInCarViewModel extends BaseViewModel<BusinessRepsitory> {
    public RFIDCallBackListener rfidService = new RFIDCallBackListener(AnalyzeImpl.TO_BOOK, tagInfo -> onScanResult(tagInfo), state -> isReading.set(state));
    private String carId;
    public ObservableField<String> carName =new ObservableField<>("请扫描书车");


    public BindingRecyclerViewAdapter adapter =new BindingRecyclerViewAdapter();
    public ObservableList<GetInCarItemViewModel> bookItemList = new ObservableArrayList<>();
    public ItemBinding<GetInCarItemViewModel> bookitemBinding = ItemBinding.of(BR.viewModel, R.layout.item_get_in_car);
    public GetInCarViewModel(@NonNull Application application) {
        super(application,BusinessRepsitory.getInstance());
        Messenger.getDefault().register(this, TOKEN_CAMERA, String.class, carId -> {
            getCarInfoById(carId);
        });
        registerRFID(rfidService);
    }
    public void onScanResult(TagInfo tagInfo){
        switch (tagInfo.getRfidModel()) {
            case TID:
                if (tagInfo.getScanModel() == AnalyzeImpl.TO_SHELF) {
//                    getShelfByTid(tagInfo.getTag());
                } else
                    getBookByTid(tagInfo.getTag());
                break;
            case EPC:
            case U_DATA:
                if (tagInfo.getScanModel() == AnalyzeImpl.TO_SHELF) {
//                    getShelfByCode(tagInfo.getTag());
                } else
                    getBookByCode(tagInfo.getTag());
                break;
        }
    }
    /**
     * 获取position的方式有很多种,indexOf是其中一种，常见的还有在Adapter中、ItemBinding.of回调里
     *
     * @return
     */
    public int getPosition(GetInCarItemViewModel item) {
        return bookItemList.indexOf(item);
    }
    /**
     * 按Tid查询书本
     *
     * @param tid 标签
     */
    private void getBookByTid(String tid) {
//        KLog.e(GetInCarViewModel.class.getSimpleName(),"开始请求"+tid);
        model.getBookByTid(tid)
                .compose(RxUtils.applySchedulersToast(getLifecycleProvider(), this))
                .subscribe(bookBean -> {
                    addItem(bookBean);
                });
    }

    private void getCarInfoById(String carId){
        model.getBookCarInfo(carId)
                .compose(RxUtils.applySchedulersToast(getLifecycleProvider(), this))
                .subscribe(bookCarBean -> {
                    this.carId = bookCarBean.getCarId();
                    carName.set(bookCarBean.getCarName());
                    List<Observable<BaseBean<BookBean>>> collect = J8Arrays.stream(bookCarBean.getBookIds().split(";"))
                            .map(s -> model.getBookByCode(s)).collect(java8.util.stream.Collectors.toList());
                    getBooks(collect);
                });
    }

    private void getBooks(List<Observable<BaseBean<BookBean>>> collect){
        Observable.merge(collect)
                .compose(RxUtils.applySchedulersToast(getLifecycleProvider(), this))
                .subscribe(bean -> addDirtyItem(bean), throwable -> {}, () -> {
                    List<GetInCarItemViewModel> dirtyitem = getDirtyData();
                    if (dirtyitem!=null&&dirtyitem.size()>0){
                        ui.showDirtyDialogEvent.postValue(dirtyitem.size());
                    }
                });
    }


    private List<GetInCarItemViewModel> getDirtyData(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return bookItemList.stream().filter(viewModel -> viewModel.isDirtyData.getValue())
                    .collect(Collectors.toList());
        }else{
            return StreamSupport.stream(bookItemList)
                    .filter(viewModel -> viewModel.isDirtyData.getValue())
                    .collect(java8.util.stream.Collectors.toList());
        }
    }
    /**
     * 按Code查询书本
     *
     * @param code 标签
     */
    private void getBookByCode(String code) {
        model.getBookByCode(code)
                .compose(RxUtils.applySchedulersToast(getLifecycleProvider(), this))
                .subscribe(bookBean ->{
                        addItem(bookBean);
                });
    }

    private void addDirtyItem(BookBean bean) {
        bookItemList.add(new GetInCarItemViewModel(this, bean,true));
    }

    /**
     * 添加项目
     *
     * @param bean 豆
     */
    /**
     * 添加项目
     *
     * @param bean 豆
     */
    private void addItem(BookBean bean) {
                bookItemList.add(new GetInCarItemViewModel(this, bean));
    }



    public void onItemRemove(GetInCarItemViewModel item) {
        int position = bookItemList.indexOf(item);
        bookItemList.remove(position);
        adapter.notifyDataSetChanged();
        ToastUtils.showShort("删除成功");
    }

    public UIChangeObservable ui =new UIChangeObservable();

    public void removeDirtyItem() {
        for (GetInCarItemViewModel viewModel : getDirtyData()) {
            onItemRemove(viewModel);

        }
    }

    public class UIChangeObservable {
        public SingleLiveEvent<String> showBind2CarDialog =new SingleLiveEvent<>();
        public SingleLiveEvent<List<BookBean>> bind2CarEvent =new SingleLiveEvent<>();
        public SingleLiveEvent<Integer> showDirtyDialogEvent =new SingleLiveEvent<>();
    }


    /**
     * 清除所有数据
     */
    public BindingCommand cleanAllData = new BindingCommand(() -> {
        cleanRFIDCacheNotStop();
        bookItemList.clear();
    });
    /**
     * 清除所有数据
     */
    public BindingCommand  bindBooks= new BindingCommand(() -> {
        cleanRFIDCache();
        checkDirtyBook();
    });
    private void checkDirtyBook(){
        if (TextUtils.isEmpty(carId)){
            ToastUtils.showShort("请先扫描书车");
            return;
        }else if (bookItemList.size()==0){
            ToastUtils.showShort("请先扫描图书");
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            tempBookBeans = bookItemList.stream()
                    .filter(viewModel -> !TextUtils.isEmpty( viewModel.book.getValue().getShelfCode()))
                    .map(viewModel -> viewModel.book.getValue())
                    .collect(Collectors.toList());
        }else{
            tempBookBeans = StreamSupport.stream(bookItemList)
                    .filter(viewModel -> !TextUtils.isEmpty( viewModel.book.getValue().getShelfCode()))
                    .map(viewModel -> viewModel.book.getValue())
                    .collect(java8.util.stream.Collectors.toList());
        }


        if (tempBookBeans==null){
            ToastUtils.showShort("扫描的图书都属于未上架图书，请先对该图书进行上架处理！");
        }else if (tempBookBeans.size()<bookItemList.size()){
//            ToastUtils.showShort("列表中存在"+(bookItemList.size()-tempBookBeans.size())+"册图书没有层架，将不会被关联到书车："+carName.get());
            ui.showBind2CarDialog.postValue("列表中存在"+(bookItemList.size()-tempBookBeans.size())+"册图书没有层架，将不会被关联到书车："+carName.get());
//            ui.showBind2CarErrorDialog.postValue("列表中存在"+(bookItemList.size()-tempBookBeans.size())+"册图书没有层架，将不会被关联到书车："+carName.get());
        }else{
            ui.showBind2CarDialog.postValue("将对"+bookItemList.size()+"册图书关联到书车：\n"+carName.get());
        }
    }
    private List<BookBean> tempBookBeans =new ArrayList<>();

    public  void bind2Car(){
        if (tempBookBeans.isEmpty()|tempBookBeans.size()==0){
            ToastUtils.showShort("暂无可上车图书");
            return;
        }
        List<BookBean> beans = BeanMapperUtils.cloneList(tempBookBeans);
        model.bindBook2Car(beans,carId)
                .compose(RxUtils.applySchedulersToast(getLifecycleProvider(), this))
                .subscribe(updateResult -> {
                    ToastUtils.showLong(updateResult.getAffactNum()+"本图书上车成功");
                    ui.bind2CarEvent.postValue(beans);
                    this.carId="";
                    this.carName.set("请扫描书车");
                    this.bookItemList.clear();
                    this.tempBookBeans.clear();
                }, throwable -> {
                    ui.bind2CarEvent.postValue(null);
                    this.carId="";
                    this.carName.set("请扫描书车");
                    this.bookItemList.clear();
                    this.tempBookBeans.clear();
                });
    }

    private List<BookBean> getBookBeans() {
        return StreamSupport.stream(bookItemList).map(viewModel -> viewModel.book.getValue()).collect(java8.util.stream.Collectors.toList());
    }

}
